package gin

import (
	"bytes"
	"io"
	"net/http"

	"gitee.com/zacyuan/yuan/pkg/json"
	"gitee.com/zacyuan/yuan/pkg/log"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

const (
	RequestIDKey = "request_id"
	RawDataKey   = "_yuan_RawData"
)

type Context struct {
	*gin.Context
}

func NewContext() *Context {
	return &Context{
		Context: &gin.Context{},
	}
}

func (c *Context) GetRequestID() string {
	requestID := c.GetString(RequestIDKey)
	if requestID == "" {
		requestID = uuid.NewString()
		c.Set(RequestIDKey, requestID)
	}

	return requestID
}

func (c *Context) GetLog() *log.SugaredLogger {
	if logger, ok := c.Get(log.GinKey); ok {
		return logger.(*log.SugaredLogger)
	}
	logger := log.WithRequestID(c.GetRequestID())
	c.Set(log.GinKey, logger)
	return logger
}

var jsonContentType = []string{"application/json; charset=utf-8"}

func (c *Context) RenderJSON(data *Return) {
	c.Context.Status(http.StatusOK)
	w := c.Context.Writer
	w.Header()["Content-Type"] = jsonContentType
	b, err := json.Marshal(data)
	if err != nil {
		logger := c.GetLog()
		logger.Error("RenderJSON marshal json with error(%v)", err)
	}
	_, err = w.Write(b)
	if err != nil {
		logger := c.GetLog()
		logger.Error("RenderJSON marshal json with error(%v)", err)
	}
}

func (c *Context) GetRawData() []byte {
	if data, ok := c.Get(RawDataKey); ok {
		return data.([]byte)
	}

	rawData, err := c.Context.GetRawData()
	if err != nil {
		rawData = make([]byte, 0)
	}
	c.Request.Body = io.NopCloser(bytes.NewBuffer(rawData))
	c.Set(RawDataKey, rawData)
	return rawData
}
